#include "IRsend.h"
#define MAX_TOKENS 8

// enum class bf_mode_t
// {
//     MODE_AUTO = 1,  // 自动模式时，消息为 on#1
//     MODE_COOL = 2,  // 制冷模式时，消息为 on#2
//     MODE_HEAT = 3,  // 制热模式时，消息为 on#3
//     MODE_FAN = 4,   // 送风模式时，消息为 on#4
//     MODE_DRY = 5,   // 除湿模式时，消息为 on#5
//     MODE_SLEEP = 6, // 睡眠模式时：消息为 on#6
//     MODE_ECO = 7,   // 节能模式时：消息为 on#7
// };

class bemfa_payload_t
{
public:
    stdAc::opmode_t mode = stdAc::opmode_t::kOff;
    bool power = false;
    bool sleep = false;
    bool econo = false;
    bool beep = false;
    bool light = false;
    float degrees = 16;
    stdAc::fanspeed_t fanspeed = stdAc::fanspeed_t::kAuto;
    stdAc::swingv_t swing_v = stdAc::swingv_t::kOff;
    stdAc::swingh_t swing_h = stdAc::swingh_t::kOff;

    bemfa_payload_t(const char *payload)
    {
        this->parse(payload);
    }
    bemfa_payload_t() {}

    void setByPayloadIndex(size_t index, const char *buffer)
    {
        if (!buffer)
        {
            return;
        }

        switch (index)
        {
        case 0:
            this->setPower(buffer);
            break;
        case 1:
            this->setMode(buffer);
            break;
        case 2:
            this->setDegrees(buffer);
            break;
        case 3:
            this->setFanspeed(buffer);
            break;
        case 4:
            this->setSwingH(buffer);
            break;
        case 5:
            this->setSwingV(buffer);
            break;
        case 6:
            this->setLight(buffer);
            break;
        case 7:
            this->setBeep(buffer);
            break;

        default:
            break;
        }
    }

    void parse(const char *payload, bool only_last = false)
    {
        // 首先复制payload，避免修改原字符串
        char payloadCopy[strlen(payload) + 1];
        strcpy(payloadCopy, payload);

        char *tokens[MAX_TOKENS];
        // 使用strtok分割字符串，注意每次调用都会修改payloadCopy
        char *token = strtok(payloadCopy, "#");

        int last_index = 0;
        for (int i = 0; i < MAX_TOKENS; i++)
        {
            tokens[i] = token;
            if (token != NULL)
            {
                last_index = i;
            }
            token = strtok(NULL, "#");
        }

        int index = -1;
        while (index < MAX_TOKENS)
        {
            index++;
            if (only_last && index != 0 && index != last_index)
            {
                continue;
            }
            this->setByPayloadIndex(index, tokens[index]);
        }
    }

    int16_t getSleep()
    {
        return this->sleep ? 0 : -1;
    }

    void set(const char *payload)
    {
        this->parse(payload, true);
    }

    void setPower(const char *_str)
    {
        this->power = strcmp(_str, "on") == 0;
    }

    void setMode(const char *_str)
    {
        switch (atoi(_str))
        {
        case 1:
            this->mode = stdAc::opmode_t::kAuto;
            this->sleep = false;
            this->econo = false;
            break;
        case 2:
            this->mode = stdAc::opmode_t::kCool;
            this->sleep = false;
            this->econo = false;
            break;
        case 3:
            this->mode = stdAc::opmode_t::kHeat;
            this->sleep = false;
            this->econo = false;
            break;
        case 4:
            this->mode = stdAc::opmode_t::kFan;
            this->sleep = false;
            this->econo = false;
            break;
        case 5:
            this->mode = stdAc::opmode_t::kDry;
            this->sleep = false;
            this->econo = false;
            break;
        case 6:
            this->sleep = true;
            break;
        case 7:
            this->econo = true;
            break;
        default:
            this->mode = stdAc::opmode_t::kOff;
            break;
        }
    }

    void setDegrees(const char *_str)
    {
        if (!_str)
        {
            Serial.print("Error: Null pointer passed to setDegrees.");
            return;
        }
        this->degrees = atoi(_str);
    }

    void setFanspeed(const char *_str)
    {
        if (!_str)
        {
            Serial.print("Error: Null pointer passed to setFanspeed.");
            return;
        }
        switch (atoi(_str))
        {
        case 0:
            this->fanspeed = stdAc::fanspeed_t::kAuto;
            break;
        case 1:
            this->fanspeed = stdAc::fanspeed_t::kMin;
            break;
        case 2:
            this->fanspeed = stdAc::fanspeed_t::kLow;
            break;
        case 3:
            this->fanspeed = stdAc::fanspeed_t::kMedium;
            break;
        case 4:
            this->fanspeed = stdAc::fanspeed_t::kHigh;
            break;
        case 5:
            this->fanspeed = stdAc::fanspeed_t::kMax;
            break;
        default:
            this->fanspeed = stdAc::fanspeed_t::kAuto;
        }
    }

    int getFanspeed()
    {
        switch (this->fanspeed)
        {
        case stdAc::fanspeed_t::kMin:
            return 1;
        case stdAc::fanspeed_t::kLow:
            return 2;
        case stdAc::fanspeed_t::kMedium:
            return 3;
        case stdAc::fanspeed_t::kHigh:
            return 4;
        case stdAc::fanspeed_t::kMax:
            return 5;
        case stdAc::fanspeed_t::kAuto:
        default:
            return 0;
        }
    }

    void setSwingH(const char *_str)
    {
        if (!_str)
        {
            Serial.print("Error: Null pointer passed to setSwingH.");
            return;
        }
        this->swing_h = strcmp(_str, "1") == 0 ? stdAc::swingh_t::kAuto : stdAc::swingh_t::kOff;
    }

    void setSwingV(const char *_str)
    {
        if (!_str)
        {
            Serial.print("Error: Null pointer passed to setSwingH.");
            return;
        }
        this->swing_v = strcmp(_str, "1") == 0 ? stdAc::swingv_t::kAuto : stdAc::swingv_t::kOff;
    }

    void setBeep(const char *_str)
    {
        this->beep = strcmp(_str, "1") == 0;
    }

    void setLight(const char *_str)
    {
        this->light = strcmp(_str, "1") == 0;
    }

    int mapModeToNumber()
    {
        int m = 1;
        if (this->econo)
        {
            m = 7;
        }
        else if (this->sleep)
        {
            m = 6;
        }
        else
        {
            switch (this->mode)
            {
            case stdAc::opmode_t::kDry:
                m = 5;
                break;
            case stdAc::opmode_t::kFan:
                m = 4;
                break;
            case stdAc::opmode_t::kHeat:
                m = 3;
                break;
            case stdAc::opmode_t::kCool:
                m = 2;
                break;
            case stdAc::opmode_t::kAuto:
                m = 1;
                break; // 添加break以修复fall through问题
            case stdAc::opmode_t::kOff:
                m = 1;
                break;
            }
        }

        return m;
    }

    void getPayload(char *&payload)
    {
        String payload_str = "";
        payload_str += this->power ? "on" : "off";
        payload_str += "#";
        int m = mapModeToNumber();

        payload_str += String(m);
        payload_str += "#";
        payload_str += String((int)this->degrees);
        payload_str += "#";
        payload_str += String(this->getFanspeed());
        payload_str += "#";
        payload_str += this->swing_h == stdAc::swingh_t::kOff ? "0" : "1";
        payload_str += "#";
        payload_str += this->swing_v == stdAc::swingv_t::kOff ? "0" : "1";
        payload_str += "#";
        payload_str += this->light ? "1" : "0";
        payload_str += "#";
        payload_str += this->beep ? "1" : "0";

        // 使用智能指针管理动态分配的内存
        std::unique_ptr<char[]> auto_payload(new char[payload_str.length() + 1]);
        strcpy(auto_payload.get(), payload_str.c_str());
        payload = auto_payload.release();
    }
};
